<?php
	// $this->start('css');
 //        echo $this->Html->css('jquery-ui/jquery-ui-1.10.3.custom.min');
 //        //echo $this->Html->css('Index/index');        
 //        echo $this->Html->css('jquery.ui.timepicker');
 //    $this->end();
 //    $this->start('script');
	// 	echo $this->Html->script("jquery-1.10.2.min");
 //        echo $this->Html->script("jquery-ui-1.10.3.custom.min");
 //        echo $this->Html->script(array(
 //            "jquery.dataTables.min", 
 //            "jquery.ui.timepicker.min", 
 //            ));
 //        //echo $this->Html->script("http://js.cit.api.here.com/se/2.5.3/jsl.js?with=all");        
	// 	//echo $this->Html->script("prediccion_mapas");
	// 	//echo $this->Html->script("prediccion_ruta");
 //    $this->end();
    $this->assign('title', "Simulacion - miBus");
	
	$recorridos_url = $this->Html->url(array("controller" => "Predicciones", "action" => "obtener_recorridos_realizados_ruta", "ext" => "json"));
	$ruta_coords_ajax = $this->Html->url(array("controller" => "Predicciones", "action" => "obtener_coordenadas_ruta", "ext" => "json"));
	$paradas_url = $this->Html->url(array("controller" => "Predicciones", "action" => "obtener_paradas_ruta", "ext" => "json"));	
	$ultima_coord_url = $this->Html->url(array("controller" => "Predicciones", "action" => "obtener_ultima_coordenada", "ext" => "json"));	
	
	$base_url = $this->Html->url('/');
?>
<script type="text/javascript" charset="UTF-8" src="http://js.cit.api.here.com/se/2.5.4/jsl.js?with=all"></script>
<script type="text/javascript" charset="UTF-8" src="<?php echo $base_url; ?>js/prediccion_mapas.js"></script>
<script type="text/javascript" charset="UTF-8" src="<?php echo $base_url; ?>js/prediccion_ruta.js"></script>
<table align="center">
	<tr>
		<td>Ruta:</td>
		<td>
			<select id="id_ruta_id" name="ruta_id" onchange="ruta_seleccionada(this.value);">										
				<option value="0" selected>[Seleccione Ruta]</option>
				<?php				
					foreach ($todas_rutas as $key => $values){
						echo "<option value=\"".$values["id_ruta"]."\">(".$values["id_ruta"].") - ".$values["nombre_ruta"]."</option>";
					}
				?>
			</select>
		</td>
		<td colspan="2"><br /></td>
	</tr>	
	<tr>
		<td>Recorrido:</td>
		<td>
			<select id="id_recorrido_realizado" name="recorrido_id">										
				<option value="0" selected>[Seleccione Recorrido]</option>
			</select>
		</td>
		<td>
			<select id="id_velocidad_simulacion" name="velocidad_simulacion">
				<option value="1.0" selected>1.0 x</option>
				<option value="1.5">1.5 x</option>
				<option value="2.0">2.0 x</option>
				<option value="2.5">2.5 x</option>
				<option value="5.0">5.0 x</option>
				<option value="10.0">10.0 x</option>
				<option value="20.0">20.0 x</option>
			</select>
		</td>
		<td>
			<input type="button" id="id_seguir_recorrido" name="seguir_recorrido" value="Seguir Recorrido" 
					onclick="iniciar_recorrido_ruta();" style="font-size: 8pt;">
		</td>
	</tr>
</table>
<table align="center">
	<tr>
		<td>
			<div id="mapContainer" style="height: 400px; width: 1050px;"></div>
		</td>
	</tr>
</table>
<table align="center">
	<tr>
		<td><input type="text" id="id_app_message" name="app_message" value="Messages..." style="font-size: 8pt;"></td>
		<td style="text-align: center;">									
			<textarea id="id_app_message_2" name="name="app_message_2" " cols="40" rows="3" style="font-size: 8pt;"></textarea>
		</td>
	</tr>
</table>
<script type="text/javascript" id="map_source">	
	var ultimo_ruta_id;
	var	ultimo_recorrido_id;
	
	var current_waypoints_ayuda = [];
	var current_paradas = [];
	var coordenadas_ruta = [];
	var paradas_posiciones;
	var porcentages_ruta;
			
	//Inicializar mapas...
	iniciar_mapas();
	
	var markersContainer = {
		buses: new nokia.maps.map.Container(), 
		rutas: new nokia.maps.map.Container(), 
		paradas: new nokia.maps.map.Container(),		
	};
	
	var icon_parada = new nokia.maps.gfx.BitmapImage("<?php echo $base_url; ?>img/parada_3.png", null, 30, 30, 0, 0);	
	var icon_desdeeia = new nokia.maps.gfx.BitmapImage("<?php echo $base_url; ?>img/bus_desde_eia.png", null, 33, 22, 0, 0);
	var busMarker = new nokia.maps.map.Marker(
		new nokia.maps.geo.Coordinate(Number(6.2359), Number(-75.5751)),{
		icon: icon_desdeeia,
		anchor: new nokia.maps.util.Point(16, 11)
	});
	var busCircleMarker = new nokia.maps.map.Circle(
		new nokia.maps.geo.Coordinate(Number(6.2359), Number(-75.5751)), 100, 
		{brush: {color:"#6EC4FFAA"}, pen: {strokeColor: "#089AFF"}}
	);
	//Solo para simulacion....
	var icon_desdeeia2 = new nokia.maps.gfx.BitmapImage("<?php echo $base_url; ?>img/bus_desde_eia2.png", null, 33, 22, 0, 0);
	var icon_desdeeia3 = new nokia.maps.gfx.BitmapImage("<?php echo $base_url; ?>img/bus_desde_eia3.png", null, 33, 22, 0, 0);
	var busMarker2 = new nokia.maps.map.Marker(
		new nokia.maps.geo.Coordinate(Number(6.2359), Number(-75.5751)),{
		icon: icon_desdeeia2,
		anchor: new nokia.maps.util.Point(16, 11)
	});
	var busMarker3 = new nokia.maps.map.Marker(
		new nokia.maps.geo.Coordinate(Number(6.2359), Number(-75.5751)),{
		icon: icon_desdeeia3,
		anchor: new nokia.maps.util.Point(16, 11)
	});

	//Estado Simulacion ...
	var count_repeated = 0;
	var principal_update_freq = 1000;
	var prediccion_update_freq = 1000;
	var intervalo_simulacion = null;
	var intervalo_prediccion = null;
	
	var sim_state;
	/*
	var last_server_coord = null;
	var last_coord_id = null;	
	var ultimo_tiempo_coordenada;
	var tiempo_inicial_coordenada;
	var sim_velocidad;	
	var posicion_actual_ruta;
	var posicion_factor_extra;
	var prediccion_posicion;
	var prediccion_factor_extra;
	var historial_posiciones;
	*/
	
	function establecer_habilitado(habilitado){
		document.getElementById('id_ruta_id').disabled = !habilitado;
		document.getElementById('id_recorrido_realizado').disabled = !habilitado;
		document.getElementById('id_velocidad_simulacion').disabled = !habilitado;
		document.getElementById('id_seguir_recorrido').disabled = !habilitado;		
	}
	
	function limpiar_combobox(combobox){
		var length = combobox.options.length;
		for (i = 0; i < length; i++) {
			combobox.options[i] = null;
		}
		
		combobox.options.length = 0;
	}

	function nueva_opcion(valor, texto){
		var extra_opcion = document.createElement('option');
		extra_opcion.text = texto;
		extra_opcion.value = valor;
		
		return extra_opcion;
	}
			
	function ruta_seleccionada(ruta_id){	
		//Actualiza el contenido del combobox
		$.get("<?php echo $recorridos_url; ?>?id_ruta=" + ruta_id, 
			function(data_recorridos){
				var combo_recorridos = document.getElementById('id_recorrido_realizado');
				limpiar_combobox(combo_recorridos);
				
				combo_recorridos.add(nueva_opcion(0,"[Seleccione Recorrido]"));
				
				for (var i = 0; i < data_recorridos.length; i++){
					combo_recorridos.add(
						nueva_opcion(data_recorridos[i].id_recorrido_realizado, 
									"(" + data_recorridos[i].id_recorrido_realizado + ") - " + data_recorridos[i].fecha_salida)
					);
				}				
			});	
	}
	
	function iniciar_recorrido_ruta(){
		var ruta_id = document.getElementById('id_ruta_id').value;
		var recorrido_id = document.getElementById('id_recorrido_realizado').value;
		
		if (ruta_id == 0){
			alert("Debe seleccionar ruta");
			return;
		}
		
		if (recorrido_id == 0){
			alert("Debe seleccionar recorrido");
			return;
		}
		
		establecer_habilitado(false);
		
		ultimo_recorrido_id = recorrido_id;
		
		if (ultimo_ruta_id != ruta_id){
			//Actualizar todo...
			ultimo_ruta_id = ruta_id;		
			
			//Recuperar coordenadas de ruta guardadas en server
			$.get("<?php echo $ruta_coords_ajax; ?>?id_ruta=" + ultimo_ruta_id, 
				function(data_recuperada){
					coordenadas_ruta = data_recuperada;											
					
					//Solicitar data de ruta para dibujarla...
					$.get("<?php echo $paradas_url; ?>?id_ruta=" + ultimo_ruta_id, coordenadas_recuperadas);			
				}
			);			
		} else {
			//Reiniciar nuevo recorrido en misma ruta...
			seguir_recorrido_ruta();
		}
	}
		
	//Funcion que grafica la ruta una vez que se ha calculado....
	var onRouteCalculated = function (observedRouter, key, value) {
		
		if (value == "finished") {
			var routes = observedRouter.getRoutes(),
				route = routes[0],
				waypoints = route.waypoints,
				i, length = waypoints.length;
			
			var lineColor = "#285999";
			
			var linea_ruta = new nokia.maps.map.Polyline(route.shape, {
				pen : new nokia.maps.util.Pen({
					lineWidth: 5, 
					strokeColor: lineColor
				}),
				arrows: new nokia.maps.util.Arrows({
					color: "#FFFFFF"
				})
			});
			
			linea_ruta.set("id_ruta", observedRouter.get("id_ruta"));
			linea_ruta.addListener("mouseover" ,  function(evt) { 
				evt.target.set("pen", new nokia.maps.util.Pen({
					lineWidth: 5, 
					strokeColor: "#F54046"
				}));
				evt.target.set("zIndex", 100);
				map.update(-1, 0);
			});
			linea_ruta.addListener("mouseout" ,  function(evt) {
				evt.target.set("pen", new nokia.maps.util.Pen({
					lineWidth: 5, 
					strokeColor: lineColor
				}));
				evt.target.set("zIndex", 2);
				map.update(-1, 0);
			});
			
			//Agregar la ruta al mapa, quitando la anterior
			map.objects.remove(markersContainer.rutas);
			markersContainer.rutas.objects.clear();
			markersContainer.rutas.objects.add(linea_ruta);
			map.objects.add(markersContainer.rutas);
			
			//Dibujar las paradas
			var waypoints_ayuda_positions = observedRouter.get("waypoints_ayuda_positions");
			var paradas_waypoints = observedRouter.get("paradas_waypoints");
			map.objects.remove(markersContainer.paradas);
			markersContainer.paradas.objects.clear();
			for (i = 0; i < length; i++) {
				if (waypoints_ayuda_positions.indexOf(i) != -1) {
					continue;
				}

				var markerParada = new nokia.maps.map.Marker(waypoints[i].originalPosition, {
					icon: icon_parada,
					anchor: new nokia.maps.util.Point(15, 15)
				});
				markerParada.parada = paradas_waypoints[i];
				
				markersContainer.paradas.objects.add(markerParada);
			}
			map.objects.add(markersContainer.paradas);
			
			//Obtener posiciones de cada parada....
			paradas_posiciones = puntos_cercanos_coordenadas(current_paradas, coordenadas_ruta);
			//Obtener porcentajes de ruta de cada coordenada de ruta...
			porcentages_ruta = obtener_porcentajes_ruta(coordenadas_ruta);
			
			//Iniciar simulacion....
			seguir_recorrido_ruta();
		} else if (value == "failed") {
			alert("Fallo en enrutamiento!");
			
			ultimo_ruta_id = null;
			ultimo_recorrido_id = null;
		}	
	};
	
	function seguir_recorrido_ruta(){
		if (coordenadas_ruta.length == 0){
			alert("Necesita guardar coordenadas de ruta en DB y actualizar para continuar");
			return;
		}
		
		if (intervalo_simulacion != null){
			clearInterval(intervalo_simulacion);
			clearInterval(intervalo_prediccion);
		}
		
		sim_state = crear_nueva_prediccion();
		sim_state.sim_velocidad = parseFloat(document.getElementById('id_velocidad_simulacion').value);
		/*
		last_server_coord = null;
		sim_velocidad = parseFloat(document.getElementById('id_velocidad_simulacion').value);
		
		posicion_actual_ruta = 0;
		posicion_factor_extra = 0.0;
		prediccion_posicion = 0;
		prediccion_factor_extra = 0.0;
		historial_posiciones = [];
		ultimo_tiempo_coordenada = new Date();	
		tiempo_inicial_coordenada = new Date();		
		*/
		
		actualizarPosicionBus(coordenadas_ruta[0].latitud, coordenadas_ruta[0].longitud);
		ajax_get_coordinate(ultimo_recorrido_id, 0);	
		
		principal_update_freq = Math.round(1000.0 / sim_state.sim_velocidad);	
		prediccion_update_freq = Math.round(1000.0 / (sim_state.sim_velocidad * 10));	
		/*		
		last_coord_id = null;
		*/
		count_repeated = 0;
		/*
		parada_actual = 0;
		parada_tiempo_siguiente = null;
		*/
		intervalo_simulacion = setInterval(continuar_recorrido_ruta, principal_update_freq);	
		intervalo_prediccion = setInterval(continuar_prediccion_ruta, prediccion_update_freq);
	}
	
	function ajax_get_coordinate(id_rr, time_delta){
	
		$.get("<?php echo $ultima_coord_url; ?>?id_recorrido_realizado=" + id_rr + "&delta=" + time_delta, 
			function(data_coord){
				if (data_coord['valida'] == 1){
					update_last_coord(data_coord);
				} else {
					sim_state.last_server_coord = null;
				}
			}
		);
	}
	
	function continuar_recorrido_ruta(){
		//asumir un segundo en tiempo simulado entre udpates...		
		var tiempo_actual = new Date();
		var delta_segundos = (tiempo_actual.getTime() - sim_state.tiempo_inicial_coordenada.getTime()) / 1000.0;	
		delta_segundos *= sim_state.sim_velocidad;	
		
		//Obtener coordenda correspondiente a tiempo simulado....
		ajax_get_coordinate(ultimo_recorrido_id, delta_segundos);
	}
	
	function continuar_prediccion_ruta(){
		var tiempo_actual = new Date();
		var delta_segundos = (tiempo_actual.getTime() - sim_state.ultimo_tiempo_coordenada.getTime()) / 1000.0;
		
		//Para la simulacion solamente...
		delta_segundos *= sim_state.sim_velocidad;
		
		var velocidades_ruta = extraer_velocidades_ruta(coordenadas_ruta);
		var prediccion = predecir_posicion_ruta(coordenadas_ruta, sim_state.posicion_actual_ruta, sim_state.posicion_factor_extra, 
												velocidades_ruta, delta_segundos, sim_state.historial_posiciones);
		if (sim_state.prediccion_posicion + sim_state.prediccion_factor_extra < prediccion.posicion + prediccion.factor){
			//re-colocar el bus si una esta en una posicion mas avanzada...
			sim_state.prediccion_posicion = prediccion.posicion;
			sim_state.prediccion_factor_extra = prediccion.factor;
			
			sim_state.prediccion_latitud = prediccion.latitud;
			sim_state.prediccion_longitud = prediccion.longitud;
			
			actualizarPosicionBus(prediccion.latitud, prediccion.longitud);					
		}
		
		//Actualizar mensaje de siguiente parada....
		//...primero actualizar siguiente parada basado en posicion actual...
		while (sim_state.parada_actual < current_paradas.length - 1 &&
			   paradas_posiciones[sim_state.parada_actual + 1].index + paradas_posiciones[sim_state.parada_actual + 1].tfact <  
			   sim_state.prediccion_posicion + sim_state.prediccion_factor_extra){
			sim_state.parada_actual++;
			sim_state.parada_tiempo_siguiente = null;
		}
		//... estimar tiempo de llegada...
		var pos_proxima_parada = paradas_posiciones[sim_state.parada_actual + 1];
		var t_llegada = predecir_tiempo_posicion(coordenadas_ruta, sim_state.prediccion_posicion, sim_state.prediccion_factor_extra, 
												velocidades_ruta, sim_state.historial_posiciones, 
												pos_proxima_parada.index, pos_proxima_parada.tfact);
		if (sim_state.parada_tiempo_siguiente == null || t_llegada <  sim_state.parada_tiempo_siguiente){
			sim_state.parada_tiempo_siguiente = t_llegada;
		}
												
		var sim_t_llegada = sim_state.parada_tiempo_siguiente / sim_state.sim_velocidad;
		//...Ahora desplegar parada y mensaje...
		if (sim_state.parada_actual < current_paradas.length - 1){
			document.getElementById('id_app_message_2').value = "Siguiente parada: " + current_paradas[sim_state.parada_actual + 1].nombre_parada + 
																", Llegada en " + pred_tiempo_texto(sim_state.parada_tiempo_siguiente) + 
																" (Tiempo Pred: " +  t_llegada.toFixed(2) + ", Tiempo Sim: " + sim_t_llegada.toFixed(2) + " )";
		} else {
			document.getElementById('id_app_message_2').value = "Destino alcanzado";
		}
	}
	
	function update_last_coord(new_server_coord){
		if (sim_state.last_coord_id == new_server_coord.id_recorrido_realizado_historico){
			count_repeated++;
		} else {
			sim_state.last_coord_id = new_server_coord.id_recorrido_realizado_historico;
			
			
			var punto_cercano;
			var coord_valida = true;
			
			if (sim_state.last_server_coord == null){
				//No hay coordenada previa, usar el mas cercano absoluto....
				//Ademas, siempre es valida....
				punto_cercano = punto_cercano_ruta_abs(new_server_coord.latitud, new_server_coord.longitud, coordenadas_ruta);							
			} else {
				//Hay coordenada previa, usar el mas cercano relativo a la ultima posicion....
				var ultimo_tiempo = dateStringToSeconds(sim_state.last_server_coord.fecha_hora_envio_servidor);
				var tiempo_actual = dateStringToSeconds(new_server_coord.fecha_hora_envio_servidor);
				var delta_tiempo = (tiempo_actual - ultimo_tiempo);
			
				punto_cercano = punto_cercano_ruta_rel(new_server_coord.latitud, new_server_coord.longitud, coordenadas_ruta,
													  sim_state.posicion_actual_ruta, sim_state.posicion_factor_extra, delta_tiempo);										                
				
				//Chequear si es valida
				// 1) primero por distancia de punto mas cercano ruta...
				if (punto_cercano.distancia > PARAMETRO_rechazo_dist &&
					porcentages_ruta[punto_cercano.index] >= PARAMETRO_rechazo_min &&
					porcentages_ruta[punto_cercano.index] <= PARAMETRO_rechazo_max){
					coord_valida = false;
				}
				
				// 2) segundo, por tiempo, solo aceptar coordenadas mas recientes...
				if (new_server_coord.fecha_hora_envio_servidor <= sim_state.last_server_coord.fecha_hora_envio_servidor){
					coord_valida = false;	
				}
			}
			
			
			if (coord_valida){
				//Reemplazar solo si es mas reciente...
				
				sim_state.historial_posiciones[sim_state.historial_posiciones.length] = {
					"fecha_hora_envio_servidor": new_server_coord.fecha_hora_envio_servidor, 
					"index": punto_cercano.index, 
					"factor": punto_cercano.tfact
				};
				
				//Actualizar posicion en ruta...
				sim_state.posicion_actual_ruta = punto_cercano.index;
				sim_state.posicion_factor_extra = punto_cercano.tfact;
				
				//Nueva ultima coordenada
				sim_state.last_server_coord = new_server_coord;
				
				sim_state.ultimo_tiempo_coordenada = new Date();	
				
				document.getElementById('id_app_message').value = sim_state.last_coord_id;
			} else {
				//Esta coordenada llego fuera de tiempo...
				document.getElementById('id_app_message').value = "Descartando " + sim_state.last_coord_id;
			}
			
			//Simulacion...
			busMarker2.coordinate = new nokia.maps.geo.Coordinate(Number(sim_state.last_server_coord.latitud), Number(sim_state.last_server_coord.longitud));		
			busMarker3.coordinate = new nokia.maps.geo.Coordinate(Number(punto_cercano.latitud), Number(punto_cercano.longitud));
		}
		
		//actualizarPosicionBus(last_server_coord.latitud, last_server_coord.longitud);	
		
		if (sim_state.last_server_coord.cuenta_coords < 1){
			clearInterval(intervalo_simulacion);
			clearInterval(intervalo_prediccion);
			intervalo_simulacion = null;
			intervalo_prediccion = null;
			alert("Simulacion Terminada!");
			alert(count_repeated);
			establecer_habilitado(true);
		}
	}
	
	
	
	function reiniciarVisualizacionBus(){
		//Remover cualquier instancia previa...
		map.objects.remove(markersContainer.buses);
		markersContainer.buses.objects.clear();
		
		//Agregar nueva instancia...
		//var container = new nokia.maps.map.Container();
		//container.objects.addAll([busMarker, busCircleMarker]);
		//markersContainer.buses.objects.add(container);
		markersContainer.buses.objects.add(busMarker);	
		markersContainer.buses.objects.add(busCircleMarker);
		//Simulacion solamente....
		markersContainer.buses.objects.add(busMarker2);	
		markersContainer.buses.objects.add(busMarker3);	
		map.objects.add(markersContainer.buses);
	}

	function actualizarPosicionBus(latitud, longitud){		
		//Actualizar coordenada de marcador
		busMarker.coordinate = new nokia.maps.geo.Coordinate(Number(latitud), Number(longitud));	
		
		busCircleMarker = new nokia.maps.map.Circle(
			new nokia.maps.geo.Coordinate(Number(latitud), Number(longitud)), 100, 
			{brush: {color:"#6EC4FFAA"}, pen: {strokeColor: "#089AFF"}}
		);
				
		reiniciarVisualizacionBus();	
			
	}
</script>